package com.cx.zyx.modulebiz.news.service.impl;

import com.cx.zyx.modulebiz.news.service.NewsStatsService;
import com.cx.zyx.modulebiz.news.service.dto.TopNewsDTO;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class NewsStatsServiceImpl implements NewsStatsService {

    private final ZSetOperations<String, Long> zSetOperations;
    private final HashOperations<String, String, Long> hashOperations;
    private final RedisTemplate<String, Long> redisTemplate;

    // 所有文章浏览量统计排名
    private static final String RANKING_VIEWS_KEY = "news:ranking:views";
    // 所有文章点赞统计排名
    private static final String RANKING_LIKES_KEY = "news:likes:views";
    // 所有文章评论数统计排名
    private static final String RANKING_COMMENTS_KEY = "news:comments:views";

    public NewsStatsServiceImpl(RedisTemplate<String, Long> redisTemplate) {
        // 文章的统计信息保存在Redis中，使用ZSet和Hash数据结构
        // 每篇文章的统计
        this.hashOperations = redisTemplate.opsForHash();
        // 所有文章统计排名
        this.zSetOperations = redisTemplate.opsForZSet();
        this.redisTemplate = redisTemplate;
    }

    /**
     * 初始化新闻统计信息
     */
    private void initNewsStats(String key) {
        hashOperations.putIfAbsent(key, "views", 0L);
        hashOperations.putIfAbsent(key, "likes", 0L);
        hashOperations.putIfAbsent(key, "comments", 0L);
        // 设置过期时间，30天
        redisTemplate.expire(key, 30, TimeUnit.DAYS);
    }

    private String getKey(Long newsId) {
        String key = "news:stats:" + newsId;;
        if(!redisTemplate.hasKey(key)) {
            initNewsStats(key);
        }
        return key;
    }

    /**
     * 增加阅读量
     */
    public void incrementViews(Long newsId) {
        String key = getKey(newsId);
        // 阅读量+1
        Long currentViews = hashOperations.increment(key, "views", 1);

        // 更新排行榜
        zSetOperations.add(RANKING_VIEWS_KEY, newsId, currentViews);
    }

    /**
     * 获取浏览量前N的文章ID列表
     * @param topN 获取前几名
     * @return 新闻ID列表，按浏览量从高到低排序
     */
    public List<TopNewsDTO> getTopViewedNews(int topN) {
        // 有序集合默认升序排列，因此需要使用reverseRange方法获取
        //Set<Long> newsIds = zSetOperations.reverseRange(RANKING_VIEWS_KEY, 0, topN - 1);
        Set<ZSetOperations.TypedTuple<Long>> newsWithScores =
                zSetOperations.reverseRangeWithScores(RANKING_VIEWS_KEY, 0, topN - 1);

        if (newsWithScores == null || newsWithScores.isEmpty()) {
            return List.of();
        }

        AtomicInteger order = new AtomicInteger(1);
        return newsWithScores.stream()
                .map(tuple -> {
                    Number value = tuple.getValue();
                    long longValue = 0L;
                    if (value != null) {
                        longValue = value.longValue();
                    }
                   return new TopNewsDTO(
                           longValue,   // newsId
                        Objects.requireNonNull(tuple.getScore()).longValue(),  // views (score)
                        order.getAndIncrement()                        // 排名
                ); })
                .collect(Collectors.toList());
    }

    /**
     * 增加点赞量
     */
    public void incrementLikes(Long newsId) {
        hashOperations.increment(getKey(newsId), "likes", 1);
    }

    /**
     * 增加评论量
     */
    public void incrementComments(Long newsId) {
        hashOperations.increment(getKey(newsId), "comments", 1);
    }

    /**
     * 获取某篇新闻的统计信息
     */
    public Map<String, Long> getStats(Long newsId) {
        return hashOperations.entries(getKey(newsId));
    }

    /**
     * 设置某个字段的值（例如手动设置）
     */
    public void setStat(Long newsId, String field, Long value) {
        hashOperations.put(getKey(newsId), field, value);
    }
}

